package com.soo.hoo.admin.component;

import com.alibaba.fastjson2.JSON;
import com.soo.hoo.core.exception.GlobalException;
import com.soo.hoo.core.model.MessagePayload;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>自定义websocket处理器</p>
 *
 * @author 杨燚
 * @since 2023/6/8
 */
@Slf4j
@Component
public class DefaultWebSocketHandler implements WebSocketHandler {

    /**
     * session池
     */
    private static final Map<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();

    /**
     * 收信人id即用户id的字段名
     */
    private static final String RECEIVER_ID_KEY = "receiverId";

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 缓存用户信息
        Object receiverId = session.getAttributes().get(RECEIVER_ID_KEY);
        if (receiverId != null) {
            SESSION_POOL.put(receiverId.toString(), session);
        }
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        // 接受消息
        Object receiverId = session.getAttributes().get(RECEIVER_ID_KEY);
        if (receiverId != null && SESSION_POOL.containsKey(receiverId.toString())) {
            SESSION_POOL.get(receiverId.toString()).sendMessage(new TextMessage("成功"));
        }
    }

    @Override
    public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable exception) throws Exception {
        // 发生错误，清除用户缓存信息
        if (session.isOpen()) {
            session.close();
        }
        Object receiverId = session.getAttributes().get(RECEIVER_ID_KEY);
        if (receiverId != null) {
            WebSocketSession wss = SESSION_POOL.remove(receiverId.toString());
            wss.close();
        }
        log.error("WebSocket发生异常：【{}】", exception.getMessage());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, @NotNull CloseStatus closeStatus) throws Exception {
        // 清除用户缓存信息
        Object receiverId = session.getAttributes().get(RECEIVER_ID_KEY);
        if (receiverId != null) {
            WebSocketSession wss = SESSION_POOL.remove(receiverId.toString());
            wss.close();
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    /**
     * 发送消息
     *
     * @param message 消息载体
     */
    public <T> void sendMessage(MessagePayload<T> message) {
        String receiver = message.getReceiver();
        if (receiver == null) {
            throw new GlobalException("收信人为空，发送消息失败");
        }
        WebSocketSession session = SESSION_POOL.get(receiver);
        if (session == null) {
            // todo 收信人不在，那就等在了再发送消息
            throw new GlobalException("待发送。。。");
        }
        try {
            session.sendMessage(new TextMessage(JSON.toJSONString(message)));
        }catch (IOException e){
            throw new GlobalException("发送消息异常，请联系管理员");
        }
    }
}
